package com.yt.common.utils;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

/**
 * @Author: gaobaozong
 * @Description: 公钥加密，解密
 * @Date: Created in 18-12-27 - 上午11:11
 * @Version: V1.0
 */
public class EncryptClient {
    private static final String KEY_ALGORITHM = "RSA";
    private static final String SIGNATURE_ALGORITHM = "RSA/ECB/PKCS1Padding";
    //private static final String SIGNATURE_ALGORITHM = "公司/sellerShopQIyuesuoDTO-金服-文档/申鑫接口文档/项目及接口文档/xgrDemo/xgrDemo/src/main/resources/";

    private static final int MAX_ENCRYPT_BLOCK = 117;

    private static final int MAX_DECRYPT_BLOCK = 128;

    private PublicKey publicKey;

    public EncryptClient(String path){
        if (path == null || "".equals(path.trim())) {
            throw new NullPointerException("密钥库不存在：" + path + ".");
        }
        try {
            CertificateFactory certificatefactory = CertificateFactory.getInstance("X.509");
            FileInputStream bais = new FileInputStream(path);
            X509Certificate Cert = (X509Certificate) certificatefactory.generateCertificate(bais);
            publicKey = Cert.getPublicKey();
        }catch (Exception e){
            e.printStackTrace();
            new RuntimeException("加载RSA公钥失败");
        }
    }

    public byte[] encrypt(byte [] data){
        try{
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            Cipher cipher = Cipher.getInstance(SIGNATURE_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            int inputLen = data.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段加密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] encryptedData = out.toByteArray();
            out.close();
            return encryptedData;
        }catch(Exception e){
            new RuntimeException("加密失败");
        }
        return null;
    }

    public byte[] decrypt(byte [] data){
        try{
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            Cipher cipher = Cipher.getInstance(SIGNATURE_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            int inputLen = data.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段解密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                    cache = cipher.doFinal(data, offSet, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_DECRYPT_BLOCK;
            }
            byte[] decryptedData = out.toByteArray();
            out.close();

            return decryptedData;
        }catch(Exception e){
            new RuntimeException("解密失败");
        }
        return null;
    }
}
